<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { useUserStore } from '@/store/modules/user';
import { type FormInstance, type FormRules } from 'element-plus';
import { User, Lock, Key, Picture, Loading } from '@element-plus/icons-vue';
import { getLoginCodeApi } from '@/api/login';
import { type LoginRequestData } from '@/api/login/types/login';
import ThemeSwitch from '@/components/ThemeSwitch/index.vue';
import Owl from './components/Owl.vue';
import { useFocus } from './hooks/useFocus';

const router = useRouter();
const { isFocus, handleBlur, handleFocus } = useFocus();

/** 登录表单元素的引用 */
const loginFormRef = ref<FormInstance | null>(null);

/** 登录按钮 Loading */
const loading = ref(false);
/** 验证码图片 URL */
const codeUrl = ref('');
/** 登录表单数据 */
const loginFormData: LoginRequestData = reactive({
	username: 'admin',
	password: '12345678',
	code: '',
});
/** 登录表单校验规则 */
const loginFormRules: FormRules = {
	username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
	password: [
		{ required: true, message: '请输入密码', trigger: 'blur' },
		{ min: 8, max: 16, message: '长度在 8 到 16 个字符', trigger: 'blur' },
	],
	code: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
};
/** 登录逻辑 */
const handleLogin = () => {
	loginFormRef.value?.validate((valid: boolean, fields) => {
		if (valid) {
			loading.value = true;
			useUserStore()
				.login(loginFormData)
				.then(() => {
					router.push({ path: '/' });
				})
				.catch(() => {
					createCode();
					loginFormData.password = '';
				})
				.finally(() => {
					loading.value = false;
				});
		} else {
			console.error('表单校验不通过', fields);
		}
	});
};
/** 创建验证码 */
const createCode = () => {
	// 先清空验证码的输入
	loginFormData.code = '';
	// 获取验证码
	codeUrl.value = '';
	getLoginCodeApi().then((res) => {
		codeUrl.value = res.data;
	});
};

/** 初始化验证码 */
createCode();
</script>

<template>
	<div class="login-container">
		<ThemeSwitch class="theme-switch" />
		<Owl :close-eyes="isFocus" />
		<div class="login-card">
			<div class="title">
				<img src="@/assets/layouts/logo-text-2.png" />
			</div>
			<div class="content">
				<el-form ref="loginFormRef" :model="loginFormData" :rules="loginFormRules" @keyup.enter="handleLogin">
					<el-form-item prop="username">
						<el-input v-model.trim="loginFormData.username" placeholder="用户名" type="text" tabindex="1" :prefix-icon="User" size="large" />
					</el-form-item>
					<el-form-item prop="password">
						<el-input
							v-model.trim="loginFormData.password"
							placeholder="密码"
							type="password"
							tabindex="2"
							:prefix-icon="Lock"
							size="large"
							show-password
							@blur="handleBlur"
							@focus="handleFocus"
						/>
					</el-form-item>
					<el-form-item prop="code">
						<el-input v-model.trim="loginFormData.code" placeholder="验证码" type="text" tabindex="3" :prefix-icon="Key" maxlength="7" size="large">
							<template #append>
								<el-image :src="codeUrl" @click="createCode" draggable="false">
									<template #placeholder>
										<el-icon>
											<Picture />
										</el-icon>
									</template>
									<template #error>
										<el-icon>
											<Loading />
										</el-icon>
									</template>
								</el-image>
							</template>
						</el-input>
					</el-form-item>
					<el-button :loading="loading" type="primary" size="large" @click.prevent="handleLogin">登 录</el-button>
				</el-form>
			</div>
		</div>
	</div>
</template>

<style lang="scss" scoped>
.login-container {
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	width: 100%;
	min-height: 100%;
	.theme-switch {
		position: fixed;
		top: 5%;
		right: 5%;
		cursor: pointer;
	}
	.login-card {
		width: 480px;
		max-width: 90%;
		border-radius: 20px;
		box-shadow: 0 0 10px #dcdfe6;
		background-color: var(--el-bg-color);
		overflow: hidden;
		.title {
			display: flex;
			justify-content: center;
			align-items: center;
			height: 150px;
			img {
				height: 100%;
			}
		}
		.content {
			padding: 20px 50px 50px 50px;
			:deep(.el-input-group__append) {
				padding: 0;
				overflow: hidden;
				.el-image {
					width: 100px;
					height: 40px;
					border-left: 0px;
					user-select: none;
					cursor: pointer;
					text-align: center;
				}
			}
			.el-button {
				width: 100%;
				margin-top: 10px;
			}
		}
	}
}
</style>
